using System.Collections.Generic;

namespace SmartMathLibrary
{
    /// <summary>
    /// Interface to implement a Polynomial class.
    /// </summary>
    public interface IPolynomial
    {
        /// <summary>
        /// Gets or sets the components of the polynomial.
        /// </summary>
        /// <value>The components of the polynomial.</value>
        List<PolynomialComponent> Components { get; }

        /// <summary>
        /// Gets the degree of the polynomial.
        /// </summary>
        /// <value>The degree of the polynomial.</value>
        double Degree { get; }

        /// <summary>
        /// Sets the component at a specified position.
        /// </summary>
        /// <param name="index">The specified position where the value should be set.</param>
        /// <param name="component">The component to set.</param>
        void SetComponentAt(int index, PolynomialComponent component);

        /// <summary>
        /// Gets a component at a specified position.
        /// </summary>
        /// <param name="index">The specified position from which the component should be returned.</param>
        /// <returns>The component of the polynomial at the specified position.</returns>
        PolynomialComponent GetComponentAt(int index);

        /// <summary>
        /// Checks if a specified rank exists.
        /// </summary>
        /// <param name="value">The rank to check.</param>
        /// <returns>True if the rank exists in the polynomial otherwise, false.</returns>
        bool ExistRank(double value);

        /// <summary>
        /// Adds a new component to the polynomial at the front of it.
        /// </summary>
        /// <param name="component">The component to add.</param>
        void AddInFrontOf(PolynomialComponent component);

        /// <summary>
        /// Sorts this polynomial by ranks.
        /// </summary>
        void Sort();

        /// <summary>
        /// Rounds the coefficients of the polynomial.
        /// </summary>
        /// <param name="decimals">The decimal precision.</param>
        void RoundCoefficients(int decimals);

        /// <summary>
        /// Raises the specified power for each coefficient of the polynomial.
        /// </summary>
        /// <param name="power">The number to raises the power.</param>
        void PowCoefficients(double power);

        /// <summary>
        /// Calculates the square root of the coefficients of the polynomial.
        /// </summary>
        void SqrtCoefficients();

        /// <summary>
        ///  Calculates the root of the coefficients of the polynomial.
        /// </summary>
        /// <param name="root">The root.</param>
        void RootCoefficients(double root);

        /// <summary>
        /// Applies the log10 to every coefficient of the polynomial.
        /// </summary>
        void Log10Coefficients();

        /// <summary>
        /// Applies the log to every coefficient of the polynomial.
        /// </summary>
        void LogCoefficients();

        /// <summary>
        /// Calculates the polynomial with a specified value for x.
        /// </summary>
        /// <param name="x">The specified value for x.</param>
        /// <returns>The result of the polynomial with the specified value for x.</returns>
        double SolveAt(double x);

        /// <summary>
        /// Determines whether the specified x is a root of the polynomial.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <returns>
        /// 	<c>true</c> if the specified x is root of the polynomial; otherwise, <c>false</c>.
        /// </returns>
        bool IsRoot(double x);

        /// <summary>
        /// Creates the first derivative of the polynomial.
        /// </summary>
        /// <returns>Returns the derivative of the polynomial.</returns>
        Polynomial Derivative();

        /// <summary>
        /// Normalizes the current polynomial.
        /// </summary>
        void Normalize();

        /// <summary>
        /// Use Horner's method to compute and return the polynomial evaluated at x.
        /// </summary>
        /// <param name="x">The x value.</param>
        /// <returns>The evaluated value of the polynomial.</returns>
        double Evaluate(int x);

        /// <summary>
        /// Calculates one root of the polynomial by using the Newton-Raphson method.
        /// </summary>
        /// <param name="startvalue">The start value.</param>
        /// <param name="iterations">The number of iterations for finding a root.</param>
        /// <returns>One root of the polynomial.</returns>
        double FindRoot(double startvalue, int iterations);

        /// <summary>
        /// Gets the coefficient with biggest exponent.
        /// </summary>
        /// <returns>The coefficient with biggest exponent.</returns>
        double GetCoefficientOfBiggestExponent();

        /// <summary>
        /// Copies the current instance of the polynomial.
        /// </summary>
        /// <returns>The current instance of the polynomial.</returns>
        Polynomial Copy();

        /// <summary>
        /// Compares the current instance of a polynomial to another one.
        /// </summary>
        /// <param name="compare">The polynomial to compare.</param>
        /// <returns>True if the polynomials are even otherwise, false.</returns>
        bool CompareTo(Polynomial compare);

        /// <summary>
        /// Removes all zero coefficients in the current polynomial.
        /// </summary>
        void RemoveZeroCoefficients();

        /// <summary>
        /// Multiplies the polynomial with a scalar.
        /// </summary>
        /// <param name="scalar">The scalar value.</param>
        void MultiplyWithScalar(int scalar);

        /// <summary>
        /// Multiplies the polynomial with a scalar.
        /// </summary>
        /// <param name="scalar">The scalar value.</param>
        void MultiplyWithScalar(double scalar);

        /// <summary>
        /// Divides the polynomial through a scalar.
        /// </summary>
        /// <param name="scalar">The scalar value.</param>
        void DivideWithScalar(int scalar);

        /// <summary>
        /// Divides the polynomial through a scalar.
        /// </summary>
        /// <param name="scalar">The scalar value.</param>
        void DivideWithScalar(double scalar);

        /// <summary>
        /// Determines whether the polynomial [has only even exponents].
        /// </summary>
        /// <returns>
        /// 	<c>true</c> if the polynomial [has only even exponents]; otherwise, <c>false</c>.
        /// </returns>
        bool HasOnlyEvenExponents();

        /// <summary>
        /// Determines whether the polynomial [has only odd exponents].
        /// </summary>
        /// <returns>
        /// 	<c>true</c> if the polynomial [has only odd exponents]; otherwise, <c>false</c>.
        /// </returns>
        bool HasOnlyOddExponents();

        /// <summary>
        /// Converts the polynomial to a complex polynomial.
        /// </summary>
        /// <returns>The converted complex polynomial.</returns>
        ComplexPolynomial ToComplexPolynomial();
    }
}